package org.smile.tomcat.session;

import java.net.InetAddress;

public class UuidSessionIdGenerator implements SessionIdGenerator{
	
	/**
	 * 82进制
	 */
	private static final char[] CHAR = {'0', '1', '2', '3', '4', '5', '6',
			'7', '8', '9','a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
			'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
			'x', 'y', 'z','A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
			'K', 'L', 'M','N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
			'X', 'Y', 'Z', '*', '-', '_','+','/','=', '~', '@', '#', '(', ')', ',',
			'.',  '?', ':', ';', '<', '>', '$', '%', '^', '&'};
	
	/** 计数器最大  最大三位表示*/
	private static final int COUNT_MAX = 36 * 36 * 36;
	/** 计数器 */
	private static int counter = 0;
	/** 36进制 */
	private static final short _36 = 36;
	/** 36进制的第五位 */
	private static final int _36_5 = 36 * 36 * 36 * 36;
	/** 36进制第四位 */
	private static final int _36_4 = 36 * 36 * 36;
	/** 本机的IP地址 */
	private static final int IP;
	/** 分隔符 */
	protected static String sep = "";
	/**标识启动时间*/
	private static final int JVM = (int) (System.currentTimeMillis() >>> 8);
	/**启动标记*/
	private static final int flag;

	static {
		int ipadd;
		try {
			ipadd = IptoInt(InetAddress.getLocalHost().getAddress());
		} catch (Exception e) {
			ipadd = 0;
		}
		IP = Math.abs(ipadd);
		flag = JVM%COUNT_MAX;
	}

	/** 把ip转成一个int类型的数字 */
	private static int IptoInt(byte[] bytes) {
		int result = 0;
		for (int i = 0; i < 4; i++) {
			result = (result << 8) - Byte.MIN_VALUE + (int) bytes[i];
		}
		return result;
	}

	protected static int getJVM() {
		return JVM;
	}

	/**
	 * 计数
	 * 
	 * @return
	 */
	protected static int getCount() {
		synchronized (UuidSessionIdGenerator.class) {
			counter++;
			if (COUNT_MAX == counter) {
				counter = 1;
			}
			return counter;
		}
	}
	
	protected static int getIP() {
		return IP;
	}

	protected static short getHiTime() {
		return (short) (System.currentTimeMillis() >>> 32);
	}

	protected static int getLoTime() {
		return Math.abs((int) System.currentTimeMillis());
	}

	protected static String format(int intval) {
		String formatted = Integer.toHexString(intval);
		StringBuilder buf = new StringBuilder("00000000");
		buf.replace(8 - formatted.length(), 8, formatted);
		return buf.toString();
	}
	/**
	 * 转换成8位字符串
	 * 
	 * @param longval
	 * @return
	 */
	protected static String format8(long longval, int radix) {
		return format(longval, radix, "00000000");
	}

	protected static String format4(int longval) {
		String formatted = Integer.toHexString(longval);
		StringBuilder buf = new StringBuilder("0000");
		buf.replace(4 - formatted.length(), 4, formatted);
		return buf.toString();
	}


	/**
	 * 转换成一个字符串
	 * 
	 * @param longval 数字
	 * @param bit 字符串的长度
	 * @param radix 转成字符串的进制数
	 * @return
	 */
	protected static String format(long longval, int radix, int bit) {
		StringBuilder buf = new StringBuilder(bit);
		for (int i = 0; i < bit; i++) {
			buf.append('0');
		}
		return format(longval, radix, buf);
	}
	/**
	 * integer 转为10位16进制
	 * 
	 * @param intval
	 * @return
	 */
	protected static String format(long intval, int radix, StringBuilder format) {
		int formatSize = format.length();
		String formatted =convertToString(intval, radix);
		int len = formatted.length();
		// 如果大小位数
		if (len > formatSize) {
			formatted = formatted.substring(len - formatSize, len);
		}
		format.replace(formatSize - formatted.length(), formatSize, formatted);
		return format.toString();
	}

	/**
	 * integer 转为10位16进制
	 * 
	 * @param intval
	 * @return
	 */
	protected static String format(long intval, int radix, String format) {
		return format(intval, radix, new StringBuilder(format));
	}

	/**
	 * smile 定义策略生成 21位
	 * @return
	 */
	@Override
	public String generate() {
		return createBuilder(sep).toString();
	}
	/**
	 * 21位id
	 * 6位ip + 9位时间 +6位count
	 * @return
	 */
	public static String create(String sep) {
		return createBuilder(sep).toString();
	}
	/**
	 * 构建uuid返回builder
	 * @param sep
	 * @return
	 */
	protected static StringBuilder createBuilder(String sep){
		StringBuilder sb = new StringBuilder(32);
		sb.append(format(getIP(), _36, "000000")).append(sep);
		sb.append(format(System.currentTimeMillis(), _36,"000000000")).append(sep);
		sb.append(format(flag * COUNT_MAX + getCount(), _36,"000000")).append(sep);
		return sb;
	}
	
	/**
	 * 转换十进制为其它进制字符串
	 * 
	 * @param i
	 * @param radix
	 * @return
	 */
	public static String convertToString(long i, int radix) {
		if (radix < Character.MIN_RADIX || radix > CHAR.length) {
			radix = 10;
		}
		if (radix == 10){
			return String.valueOf(i);
		}
		char[] buf = new char[65];
		int charPos = 64;
		boolean negative = (i < 0);

		if (!negative) {
			i = -i;
		}

		while (i <= -radix) {
			buf[charPos--] = CHAR[(int) (-(i % radix))];
			i = i / radix;
		}
		buf[charPos] = CHAR[(int) (-i)];

		if (negative) {
			buf[--charPos] = '-';
		}
		return new String(buf, charPos, (65 - charPos));
	}

}
